package com.googlecode.archimedes.filegen.generator.velocity;

import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;

import com.googlecode.archimedes.filegen.controller.GenerationException;
import com.googlecode.archimedes.filegen.generator.AbstractGenerator;
import com.googlecode.archimedes.filegen.model.Application;
import com.googlecode.archimedes.filegen.model.Asset;
import com.googlecode.archimedes.filegen.model.Entity;

/**
 * This class is a concrete implementation of AbstractGenerator. It serves to handle the handling of application scope properties, template lists and
 * entity management. Typical usage:
 * 
 * @TODO JL -- Fill out how to use this class.... More todos:
 * @TODO This should extend an abstract Bridge class (bridge between BizObj and templates)
 * @TODO This should consume... BizObjects and BizObject Templates
 * @TODO This should consume... ApplicationObjects and application Templates
 * @TODO This should consume... RuleObjects and Rule Templates
 * @TODO This should consume... IntegrationObjects and Integration Templates
 * @TODO This should consume... DataTransformationObjects and DataTransformation Templates
 * @TODO This should consume... TaskObjects and Task Templates
 * @TODO JL: remove intermingling of exec. and storage of parameters?
 * @TODO Clean up naming conventions
 * @TODO JavaDocs
 * @TODO Write package.html describing how it all works
 * @TODO Write simple logging framework?
 * @TODO LogStatements!
 * @author John Lema
 * @version $Id: VelocityApplicationGenerator.java 1983 2006-01-30 21:18:21 +0000 (Mon, 30 Jan 2006) erik $
 */

public class VelocityApplicationGenerator extends AbstractGenerator {

	private Log	logger	= LogFactory.getLog(this.getClass().getName());

	/**
	 * Loop through the Collection of assets and attempt to generate based on the Template we have been passed.
	 * 
	 * @see com.tps.filegen.generator.AbstractGenerator#generate()
	 */
	public void generate() throws GenerationException {
		Iterator iterator = this.getAssets().iterator();
		Asset asset = null;
		while (iterator.hasNext()) {
			asset = (Asset) iterator.next();

			// check to see if the template we are generating matches any assets
			if (this.getTemplate().getAllowedAssetClass().isInstance(asset)) {

				if (asset instanceof Entity) {
					generateEntity(asset);
				} else if (asset instanceof Application) {
					generateApplication(asset);
				}
			}
		}
	}

	protected VelocityUtil getVelocityUtil() {
		VelocityUtil vutil = new VelocityUtil();
		vutil.path = this.getIncludeDirectory();
		return vutil;
	}

	protected void generateEntity(Asset asset) throws GenerationException {
		if (asset instanceof Entity) {

			Entity entity = (Entity) asset;

			VelocityContext context = new VelocityContext();
			context.put("app", findApp());
			context.put("tf", getTemplate());
			context.put("bo", asset);
			context.put("vutil", getVelocityUtil());
			VelocityGenerator.generate(this, entity.getEntityName(), this.getTemplate(), context);

		} else {
			throw new GenerationException("The asset [" + asset + "] of type [" + asset.getClass().getName() + "] is not an Entity");
		}

	}

	protected void generateApplication(Asset asset) throws GenerationException {
		if (asset instanceof Application) {

			Application app = (Application) asset;

			VelocityContext context = new VelocityContext();
			context.put("app", app);
			context.put("bos", app.getEntities());
			context.put("tf", getTemplate());
			context.put("vutil", getVelocityUtil());
			VelocityGenerator.generate(this, "", this.getTemplate(), context);

		} else {
			throw new GenerationException("The asset [" + asset + "] of type [" + asset.getClass().getName() + "] is not an Application.");
		}
	}

	protected Application findApp() throws GenerationException {
		Iterator iterator = this.getAssets().iterator();
		Object asset = null;
		while (iterator.hasNext()) {
			asset = iterator.next();
			if (asset instanceof Application) {
				return (Application) asset;
			}
		}

		throw new GenerationException("Unable to find an Application object.");
	}

	protected Application findEntities() throws GenerationException {
		Iterator iterator = this.getAssets().iterator();
		Object asset = null;
		while (iterator.hasNext()) {
			asset = iterator.next();
			if (asset instanceof Application) {
				return (Application) asset;
			}
		}

		throw new GenerationException("Unable to find any entities.");
	}
}
